﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Runtime.InteropServices;
using FCNS;

namespace FCNS.Windows
{
    /// <summary>
    /// 定义窗体类
    /// </summary>
    public class Window
    {
        #region private fields
        private FCNS.WinApi.WINDOWPLACEMENT placement;
        private IntPtr handle;
        private string title;
        private int style;
        private int previousstyle;
        private IntPtr parent;
        private IntPtr previousparent;

        private static List<Window> openwnd;
        #endregion
        
        #region Properties

        public IntPtr Handle
        {
            get { return handle; }
        }

        public string Title
        {
            get { return title; }
        }

        public int Style
        {
            get { return style; }
        }

        public IntPtr Parent
        {
            get { return parent; }
        }

        public Size Size
        {
            get { return new Size(placement.rcNormalPosition.Right - placement.rcNormalPosition.Left, placement.rcNormalPosition.Bottom - placement.rcNormalPosition.Top); }
        }

        public Point Location
        {
            get { return new Point(placement.rcNormalPosition.Left, placement.rcNormalPosition.Top); }
        }

        public int PreviousStyle
        {
            get { return previousstyle; }
        }

        public Icon ExecutableIcon
        {
            get { return GetExecutableIcon(); }
        }

        public Icon WindowIcon
        {
            get { return GetWindowIcon(); }
        }

        #endregion
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="handle">窗体句柄</param>
        public Window(IntPtr handle)
        {
            this.handle = handle;

            title = gettext();
            parent = getparent();
            style = getstyle();
            GetSizeandLocation();
        }

        public void SetParent(IntPtr ParentHandle)
        {
            previousparent = WinApi.SetParent(handle, ParentHandle);
            parent = ParentHandle;
        }

        public void RestoreParent()
        {
            parent = previousparent;
            previousparent = WinApi.SetParent(handle, previousparent);
        }

        public void Move(Point Location, Size size, bool repaint)
        {
            WinApi.MoveWindow(handle, Location.X, Location.Y, size.Width, size.Height, repaint);
        }

        public void SetStyle(int index, IntPtr value)
        {
            previousstyle = WinApi.SetWindowLong(handle, index, value);
            style = value.ToInt32();
        }

        public bool Close()
        {
            bool result = WinApi.PostMessage(handle, WinApi.WM_CLOSE, 0, 0);

            if (!result)
            {
                result = WinApi.PostMessage(handle, WinApi.WM_DESTROY, 0, 0);
            }

            return result;
        }

        public void RestoreLocation()
        {
            WinApi.SetWindowPlacement(handle, ref placement);
        }

        public string GetExecutablePath()
        {
            uint dwProcessId;
            WinApi.GetWindowThreadProcessId(handle, out dwProcessId);
            IntPtr hProcess = WinApi.OpenProcess(WinApi.ProcessAccessFlags.VMRead | WinApi.ProcessAccessFlags.QueryInformation, false, dwProcessId);
            StringBuilder path = new StringBuilder(1024);
            WinApi.GetModuleFileNameEx(hProcess, IntPtr.Zero, path, 1024);
            WinApi.CloseHandle(hProcess);
            return path.ToString();
        }
        /// <summary>
        /// 获取已经在桌面打开的窗体
        /// </summary>
        /// <returns></returns>
        public static List<Window> GetOpenWindows()
        {
            openwnd = new List<Window>();

            WinApi.EnumWindowsProc callback = new WinApi.EnumWindowsProc(EnumWindows);
            WinApi.EnumWindows(callback, 0);

            List<Window> result = new List<Window>(openwnd);
            openwnd.Clear();

            result.RemoveAt(result.Count - 1);
            return result;
        }

        public static IntPtr FindWindow(string classname, string windowtitle)
        {
            return WinApi.FindWindow(classname, windowtitle);
        }

        private static bool EnumWindows(IntPtr hWnd, int lParam)
        {
            if (!WinApi.IsWindowVisible(hWnd) || hWnd == WinApi.statusbar)
                return true;

            openwnd.Add(new Window(hWnd));

            return true;
        }
        /// <summary>
        /// 获取窗体标题
        /// </summary>
        /// <returns></returns>
        private string gettext()
        {
            StringBuilder title = new StringBuilder(256);
            WinApi.GetWindowText(handle, title, 256);

            return title.ToString();
        }

        private IntPtr getparent()
        {
            return WinApi.GetParent(handle);
        }

        private int getstyle()
        {
            return WinApi.GetWindowLong(handle, WinApi.GWL_STYLE);
        }
        /// <summary>
        /// 获取窗体大小和位置
        /// </summary>
        private void GetSizeandLocation()
        {
            placement.length = Marshal.SizeOf(placement);
            WinApi.GetWindowPlacement(handle, ref placement);
        }

        private Icon GetExecutableIcon()
        {
            System.Drawing.Icon icon = null;
            string path = GetExecutablePath();
            if (System.IO.File.Exists(path))
            {
                WinApi.SHFILEINFO info = new WinApi.SHFILEINFO();
                WinApi.SHGetFileInfo(path, 0, ref info, (uint)Marshal.SizeOf(info), WinApi.SHGFI_ICON | WinApi.SHGFI_SMALLICON);

                System.Drawing.Icon temp = System.Drawing.Icon.FromHandle(info.hIcon);
                icon = (System.Drawing.Icon)temp.Clone();
                WinApi.DestroyIcon(temp.Handle);
            }

            return icon;
        }

        private Icon GetWindowIcon()
        {
            int result;

            WinApi.SendMessageTimeout(handle, WinApi.WM_GETICON, WinApi.ICON_SMALL, 0,
              WinApi.SMTO_ABORTIFHUNG, 1000, out result);

            IntPtr IconHandle = new IntPtr(result);

            if (IconHandle == IntPtr.Zero)
            {
                result = WinApi.GetClassLong(handle, WinApi.GCL_HICONSM);
                IconHandle = new IntPtr(result);
            }

            if (IconHandle == IntPtr.Zero)
            {
                WinApi.SendMessageTimeout(handle, WinApi.WM_QUERYDRAGICON, 0, 0,
                    WinApi.SMTO_ABORTIFHUNG, 1000, out result);
                IconHandle = new IntPtr(result);
            }

            if (IconHandle == IntPtr.Zero)
            {
                return null;
            }

            System.Drawing.Icon temp = System.Drawing.Icon.FromHandle(IconHandle);
            System.Drawing.Icon icon = (System.Drawing.Icon)temp.Clone();

            WinApi.DestroyIcon(IconHandle);

            return icon;
        }
    }
}
